class Watcher {
  constructor(obj, expression, callback) {
    /**
     * obj,数据对象
     * expression,表达式,如obj.a.b,配合obj取得数据
     * callback,回调
     */
    this.obj = obj
    this.expression = expression
    this.callback = callback

    // 初始化watcher实例的时候订阅数据
    this.state = this.get()
  }

  get() {
    window.target = watcher // 把watcher放到全局
    const state = this.getState()
    return state
  }

  update() {
    // 数据发生变化的时候更新
    this.state = this.getState()
    this.callback()
  }

  getState() {
    let state = this.obj
    const segments = this.expression.split('.')
    for (let key of segments) {
      if (!state) return
      state = state[key]
    }
    return state
  }
}

// 添加对象属性到响应式系统，value可以是对象
function defineReactive(obj, key, value = obj[key]) {
  const dep = [] // 给每个属性(数据)添加一个数组，用来存放watcher
  observe(value)
  Object.defineProperty(obj, key, {
    get() {
      dep.push(window.target)
      return value
    },
    set(newValue) {
      if (value === newValue) return
      value = newValue
      observe(newValue) // 如果加入的值是对象，对象中的值也要被监听
      dep.forEach(watcher => watcher.update())
    }
  })
}

// 如果有属性的嵌套呢？--> 递归遍历
function observe(obj) {
  if (typeof obj !== 'object') return
  new Observer(obj)
}

// 把obj中已有的属性添加到响应式系统
// 如果obj已有多个属性，创建Observer类来遍历obj，让obj的每个属性都可以被劫持
class Observer {
  constructor(obj) {
    this.obj = obj
    this.walk()
  }
  walk() {
    Object.keys(this.obj).forEach(key => {
      defineReactive(this.obj, key)
    })
  }
}